#!/usr/bin/env bash

# For the license, see the LICENSE file in the root directory.
#set -x

ROOT=${abs_top_builddir:-$(dirname "$0")/..}
TOPBUILD=${abs_top_builddir:-$(dirname "$0")/..}
TESTDIR=${abs_top_testdir:-$(dirname "$0")}

workdir="$(mktemp -d "/tmp/path with spaces.XXXXXX")" || exit 1

ek="80" # 2048 bit key must have highest bit set
for ((i = 1; i < 256; i++)); do
  ek="${ek}$(printf "%02x" "$i")"
done

SIGNINGKEY=${workdir}/signingkey.pem
ISSUERCERT=${workdir}/issuercert.pem
CERTSERIAL=${workdir}/certserial

PATH=${TOPBUILD}/src/swtpm_cert:$PATH

source "${TESTDIR}/common"

if ${CERTTOOL} --help | grep -q -E "\--verify-profile"; then
	verify_profile="--verify-profile=medium"
fi

trap "cleanup" SIGTERM EXIT

function cleanup()
{
	rm -rf "${workdir}"
}

cat <<_EOF_ > "${workdir}/swtpm-localca.conf"
statedir=${workdir}
signingkey = ${SIGNINGKEY}
issuercert = ${ISSUERCERT}
certserial = ${CERTSERIAL}
signingkey_password = password
_EOF_

cat <<_EOF_ > "${workdir}/swtpm-localca.options"
--tpm-manufacturer IBM
--tpm-model swtpm-libtpms
--tpm-version 2
--platform-manufacturer Fedora
--platform-version 2.1
--platform-model QEMU
_EOF_

# the following contains the test parameters and
# expected key usage
for testparams in \
	"--allow-signing|Digital signature" \
	"--allow-signing --decryption|Digital signature,Key encipherment" \
	"--decryption|Key encipherment" \
	"|Key encipherment";
do
  params=$(echo "${testparams}" | cut -d"|" -f1)
  usage=$(echo "${testparams}" | cut -d"|" -f2)

  if ! ${SWTPM_LOCALCA} \
    --type ek \
    --ek "${ek}" \
    --dir "${workdir}" \
    --vmid test \
    --tpm2 \
    --configfile "${workdir}/swtpm-localca.conf" \
    --optsfile "${workdir}/swtpm-localca.options" \
    --tpm-spec-family 2.0 --tpm-spec-revision 146 --tpm-spec-level 0 \
    ${params:+${params}}; then
    echo "Error: Test with parameters '$params' failed."
    exit 1
  fi

  # Signing key should always be password protected
  if ! grep -q "ENCRYPTED PRIVATE KEY" "${SIGNINGKEY}"; then
    echo "Error: Signing key is not password protected."
    exit 1
  fi

  # For the root CA's key we flip the password protection
  if [ -n "${SWTPM_ROOTCA_PASSWORD}" ] ;then
     if ! grep -q "ENCRYPTED PRIVATE KEY" "${workdir}/swtpm-localca-rootca-privkey.pem"; then
       echo "Error: Root CA's private key is not password protected."
       exit 1
     fi
     unset SWTPM_ROOTCA_PASSWORD
  else
     if grep -q "ENCRYPTED PRIVATE KEY" "${workdir}/swtpm-localca-rootca-privkey.pem"; then
       echo "Error: Root CA's private key is password protected but should not be."
       exit 1
     fi
     export SWTPM_ROOTCA_PASSWORD=xyz
  fi

  if [ ! -r "${workdir}/ek.cert" ]; then
    echo "Error: ${workdir}/ek.cert was not created."
    exit 1
  fi

  OIFS="$IFS"
  IFS=","

  for u in $usage; do
    echo "$u"
    if ! ${CERTTOOL} -i \
            --inder --infile "${workdir}/ek.cert" | \
            grep "Key Usage" -A2 | \
            grep -q "$u"; then
      echo "Error: Could not find key usage $u in key created " \
           "with $params."
    else
      echo "Found '$u'"
    fi
  done

  IFS="$OIFS"

  ${CERTTOOL} \
    -i \
    --inder --infile "${workdir}/ek.cert" \
    --outfile "${workdir}/ek.pem"

  if ! ${CERTTOOL} \
    --verify \
    ${verify_profile:+${verify_profile}} \
    --load-ca-certificate "${ISSUERCERT}" \
    --infile "${workdir}/ek.pem"; then
    echo "Error: Could not verify certificate chain."
    exit 1
  fi

  # Delete all keys to have CA re-created
  rm -rf "${workdir}"/*.pem
done

echo "Test 1: OK"
echo

#A few tests with odd vm Ids
for vmid in \
	"s p a c e|s p a c e" \
	"\$(ls)>foo|\$(ls)\>foo" \
	"\`ls\`&; #12|\`ls\`&\; #12" \
	"foo>&1<&2;\$(ls)|foo\>&1\<&2\;\$(ls)" \
	"'*|'*" \
	'"*|\"*' \
	":\$\$|:\$\$" \
	"\${t}[]|\${t}[]";
do
  in=$(echo "$vmid" | cut -d"|" -f1)
  exp=$(echo "$vmid" | cut -d"|" -f2)

  if ! ${SWTPM_LOCALCA} \
    --type ek \
    --ek "${ek}" \
    --dir "${workdir}" \
    --vmid "$in" \
    --tpm2 \
    --configfile "${workdir}/swtpm-localca.conf" \
    --optsfile "${workdir}/swtpm-localca.options" \
    --tpm-spec-family 2.0 --tpm-spec-revision 146 --tpm-spec-level 0 \
    ${params:+${params}} &>/dev/null; then
    echo "Error: Test with parameters '$params' failed."
    exit 1
  fi

  if [ ! -r "${workdir}/ek.cert" ]; then
    echo "Error: ${workdir}/ek.cert was not created."
    exit 1
  fi

  ac=$(${CERTTOOL} -i --inder --infile "${workdir}/ek.cert" | \
       sed -n "s/.*Subject: CN=\(.*\)$/\1/p")
  if [ "$ac" != "$exp" ]; then
    echo "Error: unexpected subject string"
    echo "actual   : $ac"
    echo "expected : $exp"
  else
    echo "Pass: $ac"
  fi
done

echo "Test 2: OK"

exit 0
